package com.ifonly.common;

/**
 * <p>
 * . 金额转换，阿拉伯数字的金额转换成中国传统的形式如
 * </p>
 *
 * @author ifonly
 * @version 1.0 2016-01-25 10:17
 * @since JDK 1.6
 */
public class CNFormatter {

    private final static String[] DECIMAL_UNITS = {"角", "分"};
    private final static String[] INTEGRAL_UNITS = {
            "圆", "拾", "佰", "仟", "万",
            "拾", "佰", "仟", "亿",
            "拾", "佰", "仟"
    };

    private final static String INTEGRAL_NO_DECIMAL = "整";
    private final static String YUAN = "圆";

    /**
     * 中文数字对应
     */
    enum CnDigit {
        ZERO("零", 0), ONE("壹", 1), TWO("贰", 2), THREE("叁", 3), FOUR("肆", 4),
        FIVE("伍", 5), SIX("陆", 6), SEVEN("柒", 7), EIGHT("捌", 8), NINE("玖", 9);

        public String cn;
        public int num;

        CnDigit(String cn, int num) {
            this.cn = cn;
            this.num = num;
        }

        public static String getCn(int num) {
            for (CnDigit cd : values()) {
                if (cd.num == num) {
                    return cd.cn;
                }
            }
            throw new IllegalArgumentException("param num error, no cn mapper for: " + num);
        }
    }

    /**
     * 将金额转中文
     *
     * @param money 金额
     * @return 大写金额
     */
    public static String format(double money) {
        return format(String.valueOf(money));
    }

    /**
     * 将金额转中文
     *
     * @param money 金额
     * @return 大写金额
     */
    private static String format(String money) {
        String arr[] = money.split("[.]");

        String part1;
        String part2;

        if (arr.length == 1) {
            part1 = arr[0];
            part2 = null;
        } else if (arr.length == 2) {
            part1 = arr[0];
            part2 = arr[1];
        } else {
            throw new IllegalArgumentException("参数错误");
        }

        boolean part1Null = isNullOrEmpty(part1);
        boolean part2Null = isNullOrEmpty(part2);

        if (part1Null && part2Null) {
            return CnDigit.getCn(0) + YUAN;
        }

        if (!part1Null && part1.length() > 12) {
            throw new IllegalArgumentException("金额过大无法计算");
        }
        if (!part2Null && part2.length() > 2) {
            throw new IllegalArgumentException("小数部分最多2位");
        }

        String integral = null; //整数部分
        String decimal = null;  //小数部分



        long n1 = 0;
        long n2 = 0;
        if (!part1Null) {
            n1 = Long.parseLong(part1);
        }
        if (!part2Null) {
            n2 = Long.parseLong(part2);
        }
        if (n1 == 0 && n2 == 0) {
            return CnDigit.getCn(0) + YUAN;
        }
        if (!part1Null) {
            integral = integral(part1);
        }
        if (!part2Null) {
            decimal = decimal(part2);
        }

        if (isNullOrEmpty(integral)) {
            if (isNullOrEmpty(decimal)) {
                return CnDigit.getCn(0) + YUAN;
            } else {
                return decimal;
            }
        }

        if (isNullOrEmpty(decimal)) {
            if (isNullOrEmpty(integral)) {
                return CnDigit.getCn(0) + YUAN;
            } else {
                return integral;
            }
        }
        return integral + decimal;
    }

    private static boolean isNullOrEmpty(String str) {
        return str == null || str.length() == 0;
    }


    private static String integral(String integral) {
        StringBuilder sb = new StringBuilder();
        char[] charArray = integral.toCharArray();
        for (int i = 0, l = charArray.length; i < l; i++) {
            char numChar = charArray[i];
            if (numChar != '0') {
                String cn = CnDigit.getCn(Character.getNumericValue(numChar));
                sb.insert(0, cn + INTEGRAL_UNITS[i]);
            }
        }
        return sb.toString();
    }

    /**
     * 小数部分处理
     *  如果是 "00" 返回 ""
     *  如果是 "x0" 返回 x角
     *  如果是 "0x" 返回 x分
     *  如果是 "xx" 返回 x角x分
     *
     * @param decimal 小数数字
     * @return 转换后金额
     */
    private static String decimal(String decimal) {
        StringBuilder sb = new StringBuilder();
        char[] charArray = decimal.toCharArray();
        for (int i = 0, l = charArray.length; i < l; i++) {
            char numChar = charArray[i];
            if (numChar != '0') {
                String cn = CnDigit.getCn(Character.getNumericValue(numChar));
                sb.append(cn).append(DECIMAL_UNITS[i]);
            }
        }
        return sb.toString();
    }

}
